from operator import itemgetter
from scipy import average
from numpy import zeros
import logging
from game import Game

class Tournament(object):
    """A round robin tournament consisting of multiple games."""
    def __init__(self,agentset,world,repetitions=100):
        self.agent_classes = agentset.get_list()
        self.num_agents = len(self.agent_classes)
        self.world = world
        self.repetitions = repetitions
        self.scores = None
 
    def _print(self, text):
        """Override if necessary to direct output to a different destination"""
        logging.info(text)
     
    def run(self):
        """Run a single iteration of the tournament, pairing all players."""
        self._print("\nROUND ROBIN TOURNAMENT WITH %s AGENTS, %s GAMES/MATCH\n"%
            (self.num_agents,self.repetitions))
        self._print('Parameters:\n'+self.world.parameters_as_str())
        cumulative_scores = zeros((self.num_agents, self.num_agents))
        self._print('Match results:')
        for i,a1 in enumerate(self.agent_classes):
            for j,a2 in enumerate(self.agent_classes[i:]):
                for r in range(self.repetitions):
                    # run game
                    agents = [a1(),a2()]
                    self.world.setup_agents(agents)
                    game = Game(agents,self.world)
                    results = game.play()
                    # record results for both players
                    if i != i+j:
                        # players are different
                        cumulative_scores[i][i+j] += results[0]
                        cumulative_scores[i+j][i] += results[1]
                    else:
                        # players are the same class, so average the scores
                        cumulative_scores[i][i] += average(results)
                # report average scores
                a1_score = cumulative_scores[i][i+j]/self.repetitions
                a2_score = cumulative_scores[i+j][i]/self.repetitions
                a1_win = '*' if a1_score >= a2_score else ''
                a2_win = '*' if a1_score <= a2_score else ''
                self._print('%s%s vs. %s%s: %s, %s'% (a1.__name__, a1_win,
                    a2.__name__, a2_win, a1_score, a2_score))
        # average the results
        self.scores = cumulative_scores / self.repetitions
        #self._print(self.scores)
        
        # report ordered results
        results = [[a.__name__,average(self.scores[i])] for i,a in 
                    enumerate(self.agent_classes)]
        results.sort(key=itemgetter(1),reverse=True)
        self._print('\nFinal rankings:')
        for i,x in enumerate(results):
            self._print('%s. %s: %.02f' % (i+1,x[0],x[1]))
        return self.scores        

                